home *** CD-ROM | disk | FTP | other *** search
/ TeX 1995 July / TeX CD-ROM July 1995 (Disc 1)(Walnut Creek)(1995).ISO / dviware / kyocera / kyofonts.c < prev    next >
C/C++ Source or Header  |  1990-10-01  |  19KB  |  669 lines

  1. /* kyofonts.c: font module for dvi printing on Kyocera laser printers
  2.  * Adapted from the qmsfonts module from Massachusetts Institute of Technology
  3.  */
  4.  
  5. #include <stdio.h>
  6. #include "util.h"
  7. #include "fonts.h"
  8. #include "findfile.h"
  9. #include "kyo.h"
  10. #include "preload.h"
  11. #include <sys/stat.h>
  12.  
  13. #define MAXDVIFONTS     256    /* Max number of fonts allowed in a DVI file*/
  14. #define MAXFNTDIR        16    /* Max number of dirs to look for fonts */
  15.  
  16. unsigned char *malloc();
  17. char *strcat();
  18. char *strcpy();
  19. char *strncpy();
  20. char *strncmp();
  21. char *strcmp();
  22.  
  23. long numerator,denominator,half_denominator,jobmag;
  24.  
  25. long     freewords = KYOMAXWORDS;    /* free space on printer */
  26. FILE     *kyo;                       /* output device */
  27. char *filter_name;                   /* the name of the calling prog */
  28. char *fntdirvec[MAXFNTDIR];
  29. int fntdirveclen;
  30.  
  31. int nkyofonts;
  32. struct kyofont *curfnt;         /* ptr to current and last font */
  33. long timestamp;                 /* Timestamp for stamping kyo fonts */
  34. int nloaded;                    /* Number of fonts already loaded */
  35. char *loadfile = PRLOAD ;
  36. char fontnums[MAXKYOFONTS];
  37.  
  38. #define PR_USED   0x0001
  39. #define PR_LOADED 0x0002
  40.  
  41. struct preload {
  42.   struct preload_info *pr_font;
  43.   short               pr_info;
  44. } loaded[MAXKYOFONTS];
  45.  
  46. /* The dvifont struct provides a (possible) many-to-one mapping
  47.  * because several DVI fonts can map to the same Kyocera font during font
  48.  * substitution.
  49.  */
  50. struct dvifont {
  51.   unsigned long    df_num;         /* DVI font number */
  52.   struct kyofont   *df_kyofont;    /* Font which contains */
  53. } dvifonts[MAXDVIFONTS];
  54. int ndvifonts;
  55.  
  56. long max(a,b)
  57.      long a,b;
  58. {
  59.   return((a>b)? a:b);
  60. }
  61.  
  62. long min(a,b)
  63.      long a,b;
  64. {
  65.   return((a<b)? a:b);
  66. }
  67.  
  68. /* called at the beginning of the driver program */
  69. f_init(printer,pgmnam,dirvec,dirveclen,num,den,mag,options)
  70.     FILE *printer;
  71.     char *pgmnam,*dirvec[];
  72.     int dirveclen;
  73.     long num,den,mag;
  74.     unsigned long options;
  75. {
  76.   int i, n, loadf;
  77.   struct stat s;
  78.   struct preload_info *fnt;
  79.  
  80.   numerator = num;
  81.   denominator = den;
  82.   half_denominator = denominator / 2;
  83.   jobmag = mag;
  84.   fntdirveclen = min(MAXFNTDIR,dirveclen);
  85.   for (i = 0; i < fntdirveclen; i++) fntdirvec[i] = dirvec[i];
  86.   ndvifonts = 0;
  87.   nkyofonts = 0;
  88.   timestamp = 0;
  89.   kyo = printer;
  90.   filter_name = pgmnam;
  91.  
  92.   /* Try to read the file with information about the
  93.    * fonts loaded in the Kyocera at this moment
  94.    * The preload file should exist and have a length
  95.    * that is a multiple of the length of a preload-record
  96.    * This to protect against corrupted preload information
  97.    * When no preload information is present or when it is corrupt
  98.    * dump an explicit DAF (delete all fonts) command
  99.    */
  100.   if (((loadf = open(loadfile, 0)) >= 0) &&
  101.       (stat(loadfile, &s) == 0) &&
  102.       (s.st_size > 0) &&
  103.       ((s.st_size % sizeof(struct preload_info)) == 0)) {
  104.       n = s.st_size / sizeof(struct preload_info);
  105.       debug("%d fonts were preloaded\n", n);
  106.       for (i=0; i<n; i++) {
  107.       if (!(loaded[nloaded].pr_font = fnt =
  108.          (struct preload_info *) malloc(sizeof(struct preload_info))))
  109.           croak("malloc %d",sizeof(struct preload_info));
  110.       loaded[nloaded++].pr_info = PR_LOADED;
  111.       if (read(loadf, fnt, sizeof(struct preload_info)) !=
  112.                    sizeof(struct preload_info)) {
  113.           nloaded--;
  114.           debug("Could read the info of only %d preloaded fonts\n",
  115.             nloaded);
  116.           break;
  117.       }
  118.       freewords -= fnt->pr_words_used;
  119.       fontnums[fnt->pr_kyonumber-KF_NUMBASE] = KF_USED;
  120.       debug("%s\n", fnt->pr_name);
  121.       }
  122.       close(loadf);
  123.   } else fprintf(kyo, "!R! DAF;EXIT;");
  124.   debug("Free font memory %ld words\n",freewords);
  125.   /* Clear the preload file before going on
  126.    * So when the driver crashes, it will not leave the next jobs
  127.    * with incorrect preload information
  128.    */
  129.   close(creat(loadfile, 0644));
  130. }
  131.  
  132. /* Called at the end of the driver program. */
  133. f_term()
  134. {
  135.   int i, j, loadf;
  136.   struct kyofont *fnt;
  137.   struct kyochar *c;
  138.   struct preload_info font;
  139.   struct preload *pfnt;
  140.  
  141.   if ((loadf = creat(loadfile, 0644)) < 0) {
  142.       debug("Cannot create %s\n", loadfile);
  143.       return;
  144.   }
  145.  
  146.   /* Just copy back the information for fonts not used by this job */
  147.   for (i=0; i<nloaded; i++) {
  148.     pfnt = &loaded[i];
  149.     if (!(pfnt->pr_info & PR_USED) &&
  150.      (pfnt->pr_info & PR_LOADED))
  151.       write(loadf, pfnt->pr_font, sizeof(struct preload_info));
  152.   }
  153.  
  154.   /* Write back the information about the fonts that are used by this job */
  155.   for (i=0; i<nkyofonts; i++) {
  156.       fnt = kyofonts[i];
  157.       if (fnt->kf_info & KF_LOADED) {
  158.       font.pr_kyonumber = fnt->kf_kyonumber;
  159.       strcpy(font.pr_name, fnt->kf_name);
  160.       font.pr_mag = fnt->kf_mag;
  161.       font.pr_words_used = fnt->kf_words_used;
  162.       font.pr_tfm_checksum = fnt->kf_tfm_checksum;
  163.       for (j=0; j<4; j++) font.pr_charvec[j] = 0;
  164.       for (j=0; j<MAXCHARS; j++) {
  165.           c = &(fnt->kf_char[j]);
  166.           if (c->kc_info & KC_LOADED)
  167.           font.pr_charvec[j/32] |= (1 << (j % 32));
  168.       }
  169.       write(loadf, &font, sizeof(struct preload_info));
  170.       }
  171.   }
  172.   debug( "Font memory left: %ld words\n", freewords);
  173. }
  174.  
  175. /* This routine provides for an independent numbering scheme
  176.  * for the fonts loaded into the Kyocera
  177.  * It returns the first free number
  178.  * Fonts are numbered starting at KF_NUMBASE
  179.  */
  180. short next_kyonumber()
  181. {
  182.   int i;
  183.  
  184.   for (i=0; i<MAXKYOFONTS; i++)
  185.     if (!fontnums[i]) {
  186.       fontnums[i] = KF_USED;
  187.       return(i+KF_NUMBASE);
  188.     }
  189. }
  190.  
  191. /* Look if font "name" is preloaded
  192.  * If it is return a pointer to the preload information
  193.  * Ohterwise return 0
  194.  */
  195. struct preload *
  196. preloaded(name, tfmchecksum, mag)
  197. char *name;
  198. long tfmchecksum;
  199. {
  200.   int i;
  201.   struct preload *pnt;
  202.   register struct preload_info *fnt;
  203.  
  204.   for (i=0; i<nloaded; i++) {
  205.       pnt = &loaded[i];
  206.       fnt = pnt->pr_font;
  207.       /* The name, magnification and tfm-checksum should match */
  208.       if ((pnt->pr_info & PR_LOADED) &&
  209.       (strcmp(fnt->pr_name, name) == 0) &&
  210.       (fnt->pr_mag == mag) &&
  211.       (fnt->pr_tfm_checksum == tfmchecksum)) {
  212.     return(pnt);
  213.       }
  214.   }
  215.   return((struct preload *) 0);
  216. }
  217.  
  218. /* Try to locate the font "name" with the specified attributes
  219.  * in "area"
  220.  */
  221. struct kyofont *
  222. find_kyofont(area,name,texmag,s,tfmchecksum)
  223.      char *area,*name;
  224.      long texmag,s,tfmchecksum;
  225. {
  226.   char fname[MAXNAMLEN],nname[128];
  227.   int i,nmag;
  228.   int mag = (texmag * 3 + 1) / 2;
  229.   struct kyofont *fnt;
  230.   struct preload *pfnt;
  231.   struct preload_info *pnt;
  232.  
  233.   /* try to find a font file */
  234.   if (!findfile(fntdirvec,fntdirveclen,area,name,mag,fname,nname,&nmag))
  235.     croak("no font %s.%d",name,texmag);
  236.  
  237.   /* make a new kyocera font */
  238.   if (nkyofonts >= MAXKYOFONTS) croak("too many kyo fonts");
  239.  
  240.   if (!(kyofonts[nkyofonts++] = fnt =
  241.     (struct kyofont *) malloc(sizeof(struct kyofont))))
  242.       croak("malloc %d",sizeof(struct kyofont));
  243.   fnt->kf_mag = nmag;
  244.   fnt->kf_timestamp = 0;
  245.   fnt->kf_s = s;
  246.   fnt->kf_tfm_checksum = tfmchecksum;
  247.   strcpy(fnt->kf_name,nname);
  248.   strcpy(fnt->kf_filename,fname);
  249.   for (i=0; i<MAXCHARS; i++)
  250.       fnt->kf_char[i].kc_info = 0;
  251.  
  252.   if (pfnt = preloaded(nname, tfmchecksum,nmag)) {
  253.       pnt = pfnt->pr_font;
  254.       fnt->kf_kyonumber = pnt->pr_kyonumber;
  255.       fnt->kf_words_needed = 0;
  256.       fnt->kf_words_used = pnt->pr_words_used;
  257.       for (i=0; i<MAXCHARS; i++)
  258.       if (pnt->pr_charvec[i/32] & ( 1 << (i % 32)))
  259.           fnt->kf_char[i].kc_info = KC_LOADED;
  260.       fnt->kf_info = KF_FILE | KF_LOADED;
  261.       pfnt->pr_info |= PR_USED;
  262.   } else {
  263.       fnt->kf_kyonumber = next_kyonumber();
  264.       fnt->kf_words_needed = KF_MIN;
  265.       fnt->kf_words_used = 0;
  266.       fnt->kf_info = KF_FILE;
  267.   }
  268.   return(fnt);
  269. }
  270.  
  271. /* Read the font information from the pxl file
  272.  * and remember that it is done
  273.  */
  274. getfontfromfile(fnt)
  275.      struct kyofont *fnt;
  276. {
  277.   char fname[MAXNAMLEN];
  278.   FILE *f;
  279.   int i;
  280.  
  281.   readpxlfile(fnt,fnt->kf_filename);
  282.   fnt->kf_info &= ~KF_FILE;
  283. }
  284.  
  285. /* Calculate the number of words needed by symbol "c"
  286.  * for its pxl raster
  287.  */
  288. int char_words_needed(c)
  289.      struct kyochar *c;
  290. {
  291.     return(((c->kc_width + 15) / 16) * c->kc_height);
  292. }
  293.  
  294. /* Define a font.
  295.  * Can be called more than once for the same font.
  296.  */
  297. f_define_font(num,options,area,name,texmag,s,tfmchecksum)
  298. char *area,*name;
  299. unsigned long num,options,texmag,s,tfmchecksum;
  300. {
  301.   int i;
  302.  
  303.   /* check to see if font is already defined */
  304.   for(i = 0; i < ndvifonts ; i++) if (dvifonts[i].df_num == num) return;
  305.  
  306.   /* Does this make too many fonts defined? */
  307.   if (ndvifonts >= MAXDVIFONTS) croak("too many dvi fonts");
  308.   dvifonts[ndvifonts].df_num = num;
  309.   dvifonts[ndvifonts++].df_kyofont = find_kyofont(area,name,texmag
  310.                          ,s,tfmchecksum);
  311. }
  312.  
  313. /* Try to find DVI font with number "fontnum"
  314.  * in the dvi-fonttable
  315.  * Timestamp it to enable LRU font removal
  316.  */
  317. struct kyofont *
  318. find_dvi_font(fontnum)
  319.      unsigned long fontnum;
  320. {
  321.   register int i;
  322.  
  323.   /* scan through the dvi font list. */
  324.   for(i = 0; i < ndvifonts ; i++)
  325.     if (dvifonts[i].df_num == fontnum) {
  326.       dvifonts[i].df_kyofont->kf_timestamp = timestamp++;
  327.       return(dvifonts[i].df_kyofont);
  328.     }
  329.   croak("no dvi font %d defined",fontnum);
  330. }
  331.  
  332. /* Select a font as the current font */
  333. f_use_font(fontnum,font_space)
  334. unsigned long fontnum;
  335. long *font_space;
  336. {
  337.   curfnt = find_dvi_font(fontnum);
  338.   /* The font should be loaded already
  339.    * because loading fonts while printing a page
  340.    * could cause the Kyocera to emit the sheet
  341.    * that is printed on at this moment
  342.    */
  343.   if (!(curfnt->kf_info & KF_LOADED))
  344.     croak("cannot load font %d while printing page", fontnum);
  345.   /* Start using it */
  346.   fprintf(kyo,"!R! FONT %1d;EXIT;",curfnt->kf_kyonumber);
  347.   *font_space = curfnt->kf_s / 6;
  348. }
  349.  
  350. /* Put symbol "ch" to the printer
  351.  * "xsize" is the horizontal width of the character in pixels
  352.  */
  353. f_setc(ch, xsize)
  354. unsigned long ch;
  355. int xsize;
  356. {
  357.   register struct kyochar *c = &(curfnt->kf_char[ch]);
  358.  
  359.   /* When the symbol is to high it must be sent in raster format
  360.    * and canoot be loaded into the Kyocera
  361.    * Symbols higher than MAXKYOHEIGHT pixels cannot be loaded
  362.    */
  363.   if (c->kc_info & KC_RASTER)
  364.     dev_raster(c);
  365.   else
  366.     dev_setc(ch, xsize);
  367. }
  368.  
  369. /* Hints as to what fonts are to be used.
  370.  * This is called once per page to give fonts module instrucions as what fonts
  371.  * and characters in those fonts have to be loaded for this page.
  372.  * "fontvec" contains a list of fonts used for this page
  373.  * "veclen" is the number of fonts used on this page
  374.  * "charvec" contains the per font information about the symbols needed
  375.  */
  376. f_newpage(fontvec,charvec,veclen)
  377.      unsigned long fontvec[];
  378.      unsigned long charvec[][4];
  379.      int veclen;
  380. {
  381.   struct kyochar *c;
  382.   register int i,j;
  383.   struct kyofont *f;
  384.  
  385.   for (i = 0; i < veclen; i++) {
  386.     /* Lookup font in the dvi-fonttable
  387.      * and read the pxlfile if needed
  388.      */
  389.     f = find_dvi_font(fontvec[i]);
  390.     if (f->kf_info & KF_FILE) getfontfromfile(f);
  391.     /* If not not loaded initialize space requirements */
  392.     if (!(f->kf_info & KF_LOADED)) {
  393.       f->kf_words_used = 0;
  394.       f->kf_words_needed = KF_MIN;
  395.  
  396.     }
  397.     /* Determine which symbols should be loaded from this font */
  398.     for (j = 0; j < MAXCHARS; j++)
  399.       if (charvec[i][j/32] & (1 << (j % 32))) {
  400.     c = &(f->kf_char[j]);
  401.     c->kc_info |= KC_NEEDED;
  402.     if (!(c->kc_info & KC_LOADED))
  403.       f->kf_words_needed += char_words_needed(c);
  404.       } else f->kf_char[j].kc_info &= ~KC_NEEDED;
  405.     /* Load the symbols needed and not yet loaded */
  406.     download_font(f);
  407.   }
  408. }
  409.  
  410.  
  411. /* Load a font into the Kyocera */
  412. download_font(fnt)
  413.      struct kyofont *fnt;
  414. {
  415.   register int i;
  416.  
  417.   /* Make free space if needed */
  418.   if (fnt->kf_words_needed > freewords)
  419.     kyofree(fnt->kf_words_needed);
  420.   freewords -= fnt->kf_words_needed;
  421.   fnt->kf_words_used += fnt->kf_words_needed;
  422.  
  423.   /* Load needed symbols that are not yet loaded */
  424.   for (i = 0; i < MAXCHARS; i++)
  425.     if ((fnt->kf_char[i].kc_info & KC_NEEDED)
  426.     && !(fnt->kf_char[i].kc_info & KC_LOADED))
  427.       load_char(i,fnt);
  428.  
  429.   /* If font is loaded for the first time set its font attributes */
  430.   if (!(fnt->kf_info & KF_LOADED))
  431.     fprintf(kyo, "!R! FONT %1d; SFA 0,0,P,0;EXIT;",fnt->kf_kyonumber);
  432.  
  433.   debug("Loaded %d words for font %s, %d\n",
  434.     fnt->kf_words_needed, fnt->kf_name, fnt->kf_kyonumber);
  435.   fnt->kf_words_needed = 0;
  436.   fnt->kf_info |= KF_LOADED;
  437. }
  438.  
  439. /* Load symbol "ch" from font "fnt" */
  440. load_char(ch,fnt)
  441.      unsigned long ch;
  442.      struct kyofont *fnt;
  443. {
  444.   register unsigned short *bp;
  445.   register int w;
  446.   struct kyochar *c = &(fnt->kf_char[ch]);
  447.   int row,bw;
  448.  
  449.   /* If symbol is too high it cannot be loaded
  450.    * and should be send as a raster each time it is used
  451.    */
  452.   if (c->kc_height > MAXKYOHEIGHT) {
  453.     c->kc_info |= KC_RASTER;
  454.     return;
  455.   }
  456.  
  457.   /* Does this symbol exist */
  458.   if (!(c->kc_glyph.l))
  459.     croak("Char %#x not in font %s\n",ch, fnt->kf_name);
  460.  
  461.   /* Load metrics information about the symbol */
  462.   fprintf(kyo, "!R! LDFC %1d,%1d,%1d,%1d,%1d,%1d,%1d,%1d,0;"
  463.      ,fnt->kf_kyonumber, visual(ch), c->kc_height, c->kc_width
  464.      ,32*c->kc_yoffset,32*c->kc_xoffset
  465.      ,32*c->kc_kyowidth, 16*c->kc_kyowidth);
  466.  
  467.   /* Load the pixel raster */
  468.   bp = c->kc_glyph.p;
  469.   bw = (c->kc_width + 15) / 16;
  470.   for (row = 0; row < c->kc_height; row++) {
  471.     for (w = 0; w < bw; w++) convert(*bp++);
  472.   }
  473.   fprintf(kyo, "; EXIT;"); fflush(kyo);
  474.   c->kc_info |= KC_LOADED;
  475. }
  476.  
  477. /* Convert pixel information into the format needed by the Kyocera */
  478. convert(w)
  479.      unsigned short w;
  480. {
  481.   char c;
  482.  
  483.   c = ((w >> 10) & 077) + 64;
  484.   if (c == 127) c = '/'; putc(c, kyo);
  485.   c = ((w >> 4) & 077) + 64;
  486.   if (c == 127) c = '/'; putc(c, kyo);
  487.   c = (w & 017) + 48; putc(c, kyo);
  488. }
  489.  
  490. /* Read the information for font "fnt" from file "fname" */
  491. int readpxlfile(fnt,fname)
  492.      struct kyofont *fnt;
  493.      char *fname;
  494. {
  495.   long pxl_id,pxl_dir_ptr;
  496.   long pxlchecksum;
  497.   FILE *f;
  498.  
  499.   if (!(f = fopen(fname,"r"))) croak("no pxl file %s",fname);
  500.   if ((pxl_id = sget4(f)) != 1001)
  501.     croak("%d bad initial pxl ID; %s doesn't look like a pxl file",
  502.       pxl_id, fnt->kf_filename);
  503.  
  504.   debug("OK This is a PXL file\n");
  505.   /* Read the last 5 longs from the pxl file */
  506.   (void) fseek(f, (long)(-5*4), 2);
  507.   pxlchecksum = sget4(f);
  508.   fnt->kf_pxl_mag_val = sget4(f);
  509.   fnt->kf_pxl_design_size = sget4(f);
  510.   pxl_dir_ptr = sget4(f);
  511.   if ((pxl_id = sget4(f)) != 1001)
  512.     croak("%d bad final pxl ID; %s doesn't look like a pxl file",
  513.       pxl_id, fnt->kf_filename);
  514.   if (pxl_dir_ptr != ftell(f) / 4 - 517)
  515.     croak("%s pxl dir ptr is %x, should be %x",
  516.       fnt->kf_filename, pxl_dir_ptr, ftell(f) / 4 - 517);
  517.   debug("pxl: checksum %d mag %d designsize %d dir %x\n",
  518.     pxlchecksum,fnt->kf_pxl_mag_val,
  519.     fnt->kf_pxl_design_size,pxl_dir_ptr);
  520.  
  521.   if (fnt->kf_tfm_checksum & (pxlchecksum != fnt->kf_tfm_checksum)) {
  522.     fprintf(stderr, "Checksum mismatch: %s\n",fnt->kf_filename);
  523.     fprintf(stderr, "   pxl file: %ld, tfm_file: %ld\n",
  524.         pxlchecksum, fnt->kf_tfm_checksum);
  525.   }
  526.  
  527.   /* Read the directory */
  528.   (void) fseek(f, pxl_dir_ptr * 4, 0);
  529.   getpxldir(fnt,f);
  530.   debug("     %s max_height=%d\n",fnt->kf_filename,fnt->kf_maxheight);
  531.  
  532.   /* Read in all the glyphs */
  533.   getglyphs(fnt,f);
  534.  
  535.   (void) fclose(f);
  536. }
  537.  
  538. /* Read the pixel directory for font "fnt" from file "f" */
  539. getpxldir(fnt,f)
  540.      struct kyofont *fnt;
  541.      FILE *f;
  542. {
  543.   int i;
  544.   struct kyochar *c;
  545.   double ds = ((double) fnt->kf_s) / ((double) (1 << 20));
  546.  
  547.   /* Each symbol has an entry of 16 bytes */
  548.   fnt->kf_maxheight = 0;
  549.   for (i = 0; i < MAXCHARS; i++) {
  550.     c = &(fnt->kf_char[i]);
  551.     c->kc_width = sget2(f);
  552.     c->kc_height = sget2(f);
  553.     c->kc_xoffset = sget2(f);
  554.     c->kc_yoffset = sget2(f);
  555.     c->kc_glyph.l = get4(f);
  556.     c->kc_pxlwidth = sget4(f);
  557.     c->kc_texwidth = (long) (((double) c->kc_pxlwidth) * ds);
  558.     c->kc_kyowidth =
  559.          (c->kc_texwidth * numerator + half_denominator) / denominator;
  560.     /* Determine the maximum height of the font */
  561.     fnt->kf_maxheight = max(fnt->kf_maxheight,c->kc_height);
  562.   }
  563. }
  564.  
  565. /* Read the raster information for font "fnt" from file "f"
  566.  * The information per symbol is a multiple of 4 bytes
  567.  * The information per symbol that will be loaded is a multiple of 2 bytes
  568.  */
  569. getglyphs(fnt,f)
  570.      struct kyofont *fnt;
  571.      FILE *f;
  572. {
  573.   register int j,row;
  574.   register unsigned short *p;
  575.   int i,fbw,bw;
  576.   struct kyochar *c;
  577.  
  578.   for (i = 0; i < MAXCHARS; i++) {
  579.     c = &(fnt->kf_char[i]);
  580.     if (c->kc_glyph.l) {
  581.       (void) fseek(f, c->kc_glyph.l * 4, 0);
  582.       fbw = ((c->kc_width + 31) / 32) * 2;
  583.       bw = (c->kc_width + 15) / 16;
  584.       if (!(p = (unsigned short *)malloc(2*bw * c->kc_height)))
  585.     croak("malloc %d",2*bw * c->kc_height);
  586.       c->kc_glyph.p = p;
  587.       for (row = 0; row < c->kc_height; row++) {
  588.     for (j = 0; j < bw; j++) *p++ = get2(f);
  589.     /* get rid of empty trailing bytes */
  590.     for (j = bw; j < fbw; j++) (void) get2(f);
  591.       }
  592.     }
  593.   }
  594. }
  595.  
  596. /* This procedure is called for every character so it must be fast
  597.  * It returns the TeX width and the device width of symbol "ch"
  598.  */
  599. f_use_char(ch,texwidth,devwidth)
  600. unsigned long ch;
  601. long *texwidth,*devwidth;
  602. {
  603.   register struct kyochar *c = &(curfnt->kf_char[ch]);
  604.  
  605.   *texwidth = c->kc_texwidth;
  606.   *devwidth = c->kc_kyowidth;
  607. }
  608.  
  609.  
  610. /* free words by deleting font(s) using LRU strategy
  611.  * at least "words" words should be free
  612.  */
  613. int kyofree(words)
  614.      int words;
  615. {
  616.   int i,oldtime;
  617.   struct kyofont *oldfont;
  618.   struct preload *oldpr;
  619.  
  620.   while (words > freewords) {
  621.     oldpr = NULL;
  622.     /* First try preloaded fonts not yet used by this job */
  623.     for (i=0; i<nloaded; i++)
  624.       if (loaded[i].pr_info & PR_LOADED) {
  625.     oldpr = &loaded[i];
  626.     break;
  627.       }
  628.     /* Found one, delete it */
  629.     if (oldpr) {
  630.       oldpr->pr_info &= ~PR_LOADED;
  631.       fprintf(kyo,"!R! DELF %1d;EXIT;",oldpr->pr_font->pr_kyonumber);
  632.       fflush(kyo);
  633.       debug("Left free %ld\n", freewords);
  634.       debug("PRELOADED FONT %s, %d deleted, size %ld\n",
  635.         oldpr->pr_font->pr_name,
  636.         oldpr->pr_font->pr_kyonumber,
  637.         oldpr->pr_font->pr_words_used );
  638.       freewords += oldpr->pr_font->pr_words_used;
  639.     } else {
  640.       /* Try the other fonts now */
  641.       oldfont = NULL;
  642.       oldtime = timestamp;
  643.       for (i = 0; i < nkyofonts; i++)
  644.     if ((kyofonts[i]->kf_info & KF_LOADED)
  645.         && (kyofonts[i]->kf_timestamp < oldtime)) {
  646.       oldfont = kyofonts[i];
  647.       oldtime = oldfont->kf_timestamp;
  648.     }
  649.       if (!oldfont) croak("kyofree bug");
  650.       oldfont->kf_info &= ~KF_LOADED;
  651.       oldfont->kf_words_needed = KF_MIN;
  652.       oldfont->kf_words_used = 0;
  653.       fprintf(kyo,"!R! DELF %1d;EXIT;",oldfont->kf_kyonumber);
  654.       fflush(kyo);
  655.       debug("Left free %ld\n", freewords);
  656.       debug("FONT %s, %d deleted, size %ld\n",
  657.         oldfont->kf_name,
  658.         oldfont->kf_kyonumber,
  659.         oldfont->kf_words_used);
  660.       freewords += oldfont->kf_words_used;
  661.       for (i = 0; i < MAXCHARS; i++) {
  662.     oldfont->kf_char[i].kc_info &= ~KC_LOADED;
  663.     if (oldfont->kf_char[i].kc_info & KC_NEEDED)
  664.       oldfont->kf_words_needed+=char_words_needed(&(oldfont->kf_char[i]));
  665.       }
  666.     }
  667.   }
  668. }
  669.